package com.seeyon.ctp.rest.resources;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.seeyon.ctp.api.annotation.ApiOperation;
import com.seeyon.ctp.common.file.model.CtpFile;
import com.seeyon.ctp.common.i18n.util.I18nUtil;
import com.seeyon.ctp.portal.util.PortalCssEngine;
import com.seeyon.ctp.portal.section.util.SectionUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.SystemEnvironment;
import com.seeyon.ctp.common.authenticate.domain.User;
import com.seeyon.ctp.common.constants.Constants.login_useragent_from;
import com.seeyon.ctp.common.constants.SystemProperties;
import com.seeyon.ctp.common.customize.manager.CustomizeManager;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.filemanager.manager.FileManager;
import com.seeyon.ctp.common.i18n.ResourceUtil;
import com.seeyon.ctp.common.po.customize.CtpCustomize;
import com.seeyon.ctp.common.po.filemanager.V3XFile;
import com.seeyon.ctp.organization.OrgConstants;
import com.seeyon.ctp.organization.bo.V3xOrgAccount;
import com.seeyon.ctp.organization.bo.V3xOrgDepartment;
import com.seeyon.ctp.organization.bo.V3xOrgMember;
import com.seeyon.ctp.organization.bo.V3xOrgPost;
import com.seeyon.ctp.organization.dao.OrgHelper;
import com.seeyon.ctp.organization.manager.OrgManager;
import com.seeyon.ctp.portal.api.PortalSetInterface;
import com.seeyon.ctp.portal.api.PortalSetInterfaceManager;
import com.seeyon.ctp.portal.manager.PortalCacheManager;
import com.seeyon.ctp.portal.manager.PortalIconStyleManager;
import com.seeyon.ctp.portal.manager.PortalManager;
import com.seeyon.ctp.portal.manager.PortalNavManager;
import com.seeyon.ctp.portal.manager.PortalThemeManager;
import com.seeyon.ctp.portal.manager.SlideVPortalManager;
import com.seeyon.ctp.portal.mobile.manager.MobilePortalManager;
import com.seeyon.ctp.portal.nav.bo.NavEnum;
import com.seeyon.ctp.portal.nav.bo.PortalNavBo;
import com.seeyon.ctp.portal.po.PortalIconStyle;
import com.seeyon.ctp.portal.po.PortalNav;
import com.seeyon.ctp.portal.po.PortalSet;
import com.seeyon.ctp.portal.po.PortalSkin;
import com.seeyon.ctp.portal.po.PortalSkinSet;
import com.seeyon.ctp.portal.po.PortalSpaceFix;
import com.seeyon.ctp.portal.po.PortalTemplate;
import com.seeyon.ctp.portal.po.PortalTheme;
import com.seeyon.ctp.portal.po.SlideVPortalPO;
import com.seeyon.ctp.portal.section.BaseSection;
import com.seeyon.ctp.portal.section.SectionManager;
import com.seeyon.ctp.portal.section.SectionProperty;
import com.seeyon.ctp.portal.section.SectionReference;
import com.seeyon.ctp.portal.section.SectionReferenceImpl.ValueType;
import com.seeyon.ctp.portal.section.SectionReferenceValueRange;
import com.seeyon.ctp.portal.section.SectionRegisterManager;
import com.seeyon.ctp.portal.space.bo.SpaceBO;
import com.seeyon.ctp.portal.space.manager.PageManager;
import com.seeyon.ctp.portal.space.manager.PortletEntityPropertyManager;
import com.seeyon.ctp.portal.space.manager.SpaceManager;
import com.seeyon.ctp.portal.util.Constants;
import com.seeyon.ctp.portal.util.Constants.SpaceType;
import com.seeyon.ctp.portal.util.PortalConstants;
import com.seeyon.ctp.portal.weather.manager.WeatherAreaInfoManager;
import com.seeyon.ctp.portal.weather.po.Weather;
import com.seeyon.ctp.util.ParamUtil;
import com.seeyon.ctp.util.Strings;
import com.seeyon.ctp.util.json.JSONUtil;

/**
 * V-Join portal
 *
 */
@Path("mobilePortal")
@Produces({ MediaType.APPLICATION_JSON })
public class MobilePortalResource extends BaseResource {

    private static final Log             log = LogFactory.getLog(MobilePortalResource.class);
    
    private static final String Etag_Prefix= SystemEnvironment.getServerStartTime()+"_";
    
    private static final int Etag_CacheDate = 1000 * 60 * 60 * 12 * 7;
    
    private static final String C_VALUE = "member_mobile_space_";

    private PortalCacheManager           portalCacheManager;
    private SectionManager               sectionManager;
    private MobilePortalManager          mobilePortalManager;
    private CustomizeManager             customizeManager;
    private SectionRegisterManager       sectionRegisterManager;
    private PageManager                  pageManager;
    private SpaceManager                 spaceManager;
    private PortletEntityPropertyManager portletEntityPropertyManager;
    private SlideVPortalManager          slideVPortalManager;
    private PortalThemeManager		     portalThemeManager;
    private PortalManager		         portalManager;
    private PortalIconStyleManager       portalIconStyleManager;
    private FileManager                	 fileManager;
    private WeatherAreaInfoManager       weatherAreaInfoManager;

    public OrgManager getOrgManager() {
        if(orgManager==null){
            orgManager=(OrgManager) AppContext.getBean("orgManager");
        }
        return orgManager;
    }

    public void setOrgManager(OrgManager orgManager) {
        this.orgManager = orgManager;
    }

    private OrgManager orgManager;

    public PortalNavManager getPortalNavManager() {
        if(portalNavManager==null){
            portalNavManager=(PortalNavManager) AppContext.getBean("portalNavManager");
        }
        return portalNavManager;
    }

    public void setPortalNavManager(PortalNavManager portalNavManager) {
        this.portalNavManager = portalNavManager;
    }

    private PortalNavManager portalNavManager;
    
    public PortalIconStyleManager getPortalIconStyleManager() {
        if (portalIconStyleManager == null) {
        	portalIconStyleManager = (PortalIconStyleManager) AppContext.getBean("portalIconStyleManager");
        }
        return portalIconStyleManager;
    }

    public PortalCacheManager getPortalCacheManager() {
        if (portalCacheManager == null) {
            portalCacheManager = (PortalCacheManager) AppContext.getBean("portalCacheManager");
        }
        return portalCacheManager;
    }

    public SectionManager getSectionManager() {
        if (sectionManager == null) {
            sectionManager = (SectionManager) AppContext.getBean("sectionManager");
        }
        return sectionManager;
    }

    public MobilePortalManager getMobilePortalManager() {
        if (mobilePortalManager == null) {
            mobilePortalManager = (MobilePortalManager) AppContext.getBean("mobilePortalManager");
        }
        return mobilePortalManager;
    }

    public CustomizeManager getCustomizeManager() {
        if (customizeManager == null) {
            customizeManager = (CustomizeManager) AppContext.getBean("customizeManager");
        }
        return customizeManager;
    }

    public SectionRegisterManager getSectionRegisterManager() {
        if (sectionRegisterManager == null) {
            sectionRegisterManager = (SectionRegisterManager) AppContext.getBean("sectionRegisterManager");
        }
        return sectionRegisterManager;
    }

    public PageManager getPageManager() {
        if (pageManager == null) {
            pageManager = (PageManager) AppContext.getBean("pageManager");
        }
        return pageManager;
    }

    public SpaceManager getSpaceManager() {
        if (spaceManager == null) {
            spaceManager = (SpaceManager) AppContext.getBean("spaceManager");
        }
        return spaceManager;
    }

    public PortletEntityPropertyManager getPortletEntityPropertyManager() {
        if (portletEntityPropertyManager == null) {
            portletEntityPropertyManager = (PortletEntityPropertyManager) AppContext.getBean("portletEntityPropertyManager");
        }
        return portletEntityPropertyManager;
    }

    public PortalManager getPortalManager() {
        if (portalManager == null) {
            portalManager = (PortalManager) AppContext.getBean("portalManager");
        }
        return portalManager;
    }

    public WeatherAreaInfoManager getWeatherAreaInfoManager() {
    	if (weatherAreaInfoManager == null) {
			weatherAreaInfoManager = (WeatherAreaInfoManager) AppContext.getBean("weatherAreaInfoManager");
        }
        return weatherAreaInfoManager;
	}

	public void setWeatherAreaInfoManager(
			WeatherAreaInfoManager weatherAreaInfoManager) {
		this.weatherAreaInfoManager = weatherAreaInfoManager;
	}

	/**
     * 获取所有门户
     * @param spaceCategory 门户类别：目前必须传入为mobile
     * @return List<Map<String,String>>:
     * [
     * {"portalType":"1","portalId":"门户ID","portalName":"门户名称1","iconUrl":"门户图标1"},
     * {"portalType":"1","portalId":"门户ID","portalName":"门户名称2","iconUrl":"门户图标2"}
     * ]
     * @throws BusinessException
     */
    @GET
    @Path("portals/{spaceCategory}")
    @ApiOperation(name = "获取所有门户", scenes = "M3：获取所有门户")
    public Response getPortals(@PathParam("spaceCategory") String spaceCategory) throws BusinessException {
        try {
            List<Map<String, String>> list = new ArrayList<Map<String, String>>();
            User user = AppContext.getCurrentUser();
            if (!user.isV5Member()) {//V-Join
                Map<String, String> map = new HashMap<String, String>();
                map.put("portalType", "vjoin");
                map.put("portalId", "-1");
                map.put("portalName", "vjoin");
                map.put("iconUrl", "");
                list.add(map);
                return success(list, "", 200);
            }
            //【个人信息门户】升级更名：升级后门户更名为“信息门户”
            List<Map<String, String>> mainlist = new ArrayList<Map<String, String>>();
            List<Map<String, String>> sublist = new ArrayList<Map<String, String>>();
            List<Map<String, String>> crossUnitlist = new ArrayList<Map<String, String>>();
            List<Map<String, String>> comprehensivelist = new ArrayList<Map<String, String>>();
            List<PortalSet> portals = getPortalCacheManager().getPortalSets(AppContext.getCurrentUser(), spaceCategory);
            if (Strings.isNotEmpty(portals)) {
                for (PortalSet portal : portals) {
                	Map<String, String> map = new HashMap<String, String>();
                    map.put("portalType", "mobile");
                    map.put("portalId", portal.getId().toString());
                    if("2".equals(portal.getId().toString())){
                        //集团管理员的主门户过滤掉
                        continue;
                    }
                    String portalName= ResourceUtil.getString(portal.getPortalName());
                    if(portal.getAccountId().longValue()!=user.getLoginAccount() 
                    		&& portal.getAccountId().longValue()!=0 
                    		&& portal.getAccountId().longValue()!=OrgConstants.GROUPID){
                    	OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager");
                    	V3xOrgAccount account = orgManager.getAccountById(portal.getAccountId());
                    	if(null!=account){
                    		portalName= portalName+"("+account.getShortName()+")";
                    	}
                    }
                    map.put("portalName", portalName);
                    map.put("iconUrl", portal.getImgId());
                    boolean masterPortal = getPortalManager().isMobileMasterPortal(portal);
                    if(masterPortal && portal.getAccountId().equals(user.getLoginAccount())){//只取所登录单位的移动信息主门户
                		map.put("masterPortal", "1");
                		mainlist.add(map);
                	}else{//子门户
	                    map.put("masterPortal", "0");
	                    if(portal.getPortalType()==5){
	                    	comprehensivelist.add(map);
	                    }else if(portal.getAccountId().longValue()!=user.getLoginAccount() 
	                    		&& portal.getAccountId().longValue()!=0 
	                    		&& portal.getAccountId().longValue()!=OrgConstants.GROUPID){
	                        if(!masterPortal){
                                crossUnitlist.add(map);
                            }
	                    }else{
	                    	sublist.add(map);
	                    }
                	}
                }
            }
            List<Map<String, String>> cap4list1 = new ArrayList<Map<String, String>>();
            PortalSetInterface portalSetInterface= PortalSetInterfaceManager.getPortalSet("5");
        	if(null!=portalSetInterface){
        		List<PortalNavBo> cap4list= portalSetInterface.getAllMobilePortalNav();
        		if(null!=cap4list){
        			for (PortalNavBo portalNavBo : cap4list) {
        				Map<String, String> map = new HashMap<String, String>();
                        map.put("portalType", "cap4mobile");
                        map.put("portalId", portalNavBo.getId().toString());
                        map.put("portalName", portalNavBo.getNavName());
                        map.put("iconUrl", portalNavBo.getIcon());
                        cap4list1.add(map);
					}
        		}
        	}
        	if(null!=mainlist && !mainlist.isEmpty()){
        		list.addAll(mainlist);
        	}
        	if(null!=sublist && !sublist.isEmpty()){
        		list.addAll(sublist);
        	}
        	if(null!=crossUnitlist && !crossUnitlist.isEmpty()){
        		list.addAll(crossUnitlist);
        	}
        	if(null!=comprehensivelist && !comprehensivelist.isEmpty()){
        		list.addAll(comprehensivelist);
        	}
        	if(null!=cap4list1 && !cap4list1.isEmpty()){
        		list.addAll(cap4list1);
        	}
            return success(list, "", 200);
        } catch (Exception e) {
            /*log.error("获取门户失败,错误:" + e.getMessage(), e);
            return fail("获取门户失败,错误:" + e.getMessage(), 500);*/
            log.error("Acquisition portal failed, error:" + e.getMessage(), e);
            return fail("Acquisition portal failed, error:" + e.getMessage(), 500);
        }
    }

    /**
     * 根据门户ID获取所有空间
     * @param portalId 门户ID
     * @return List<Map<String,String>>
     * [
     * {"spaceId":"空间ID1","spaceName":"空间名称1","iconUrl":"空间图标1","spacePath":"空间url1","spaceType":"空间类型"},
     * {"spaceId":"空间ID2","spaceName":"空间名称2","iconUrl":"空间图标2","spacePath":"空间url2","spaceType":"空间类型"}
     * ]
     * @throws BusinessException
     */
    @GET
    @Path("spaces/{portalId}")
    @ApiOperation(name = "根据门户ID获取所有空间", scenes = "M3：根据门户ID获取所有空间")
    public Response getSpaces(@PathParam("portalId") String portalId) throws BusinessException {
        if (!(AppContext.hasPlugin("m3") || AppContext.hasPlugin("weixin"))) {
            return fail(ResourceUtil.getString("common.no.rest.label"));
        }
        
        try {
            String spaceCategory = "mobile";
            Map<String, Object> result= getSpacesInner(spaceCategory, portalId);
            return success(result, "", 200);
        } catch (Exception e) {
            log.error("Space acquisition failed, error", e);
            //return fail("空间获取失败,错误:" + e.getMessage(), 500);
            return fail("Space acquisition failed, error:" + e.getMessage(), 500);
        }
    }

    private Map<String, Object> getSpacesInner(String spaceCategory,String portalId) throws BusinessException {
    	if(AppContext.getCurrentUser().isVJoinMember()){//vjoin下 传的portalId实为spaceId
    	    boolean isreportPortal = false;
            if (Strings.isLong(portalId)) {
                PortalSet portalSetFromCache = portalCacheManager.getPortalSetFromCache(Long.valueOf(portalId));
                if (portalSetFromCache != null) {
                    Integer portalType = portalSetFromCache.getPortalType();
                    if (portalType != null && portalType == 4) {
                        isreportPortal = true;
                    }
                }
            }
            if (!isreportPortal) {
                List<Map<String, String>> data = new ArrayList<Map<String, String>>();
                Map<String, Object> vjoinSpaceMap = getMobilePortalManager().getSpaceMapByAccess("mobile", AppContext.currentUserId());
                for(String path : vjoinSpaceMap.keySet()){
                    Map space = (Map)vjoinSpaceMap.get(path);
                    Map<String, String> spa = new HashMap<String, String>();
                    spa.put("spaceId", space.get("id").toString());
                    spa.put("spaceName", (String)space.get("spaceName"));
                    spa.put("iconUrl", "");
                    spa.put("spacePath", (String)space.get("path"));
                    spa.put("spaceType", "");
                    data.add(spa);
                }
                Map<String, Object> result = new HashMap<String, Object>();
                result.put("data", data);
                return result;
            }else {
                User user = AppContext.getCurrentUser();
                List<SpaceBO> spaces = getPortalCacheManager().getSpaceBoList(user, spaceCategory, portalId);
                List<Map<String, String>> data = new ArrayList<Map<String, String>>();
                for (SpaceBO space : spaces) {
                    Map<String, String> spa = new HashMap<String, String>();
                    spa.put("spaceId", space.getSpaceId());
                    spa.put("spaceName", space.getSpaceName());
                    spa.put("iconUrl", space.getSpaceIcon());
                    spa.put("spacePath", space.getSpacePath());
                    spa.put("spaceType", space.getSpaceType());
                    data.add(spa);
                }
                Map<String, Object> result = new HashMap<String, Object>();
                result.put("data", data);
                return result;
            }
        }else{
            User user = AppContext.getCurrentUser();
            List<SpaceBO> spaces = getPortalCacheManager().getSpaceBoList(user, spaceCategory, portalId);
            List<Map<String, String>> data = new ArrayList<Map<String, String>>();
            for (SpaceBO space : spaces) {
                Map<String, String> spa = new HashMap<String, String>();
                spa.put("spaceId", space.getSpaceId());
                spa.put("spaceName", space.getSpaceName());
                spa.put("iconUrl", space.getSpaceIcon());
                spa.put("spacePath", space.getSpacePath());
                spa.put("spaceType", space.getSpaceType());
                String state = space.getState();
                SpaceBO defaultSpaceFix = getSpaceManager().getRealDefaultSpaceFix(space);
                if (defaultSpaceFix != null) {
                    state=defaultSpaceFix.getState();
                }
                if ("1".equals(state)) {
                    //停用的给过滤掉
                    continue;
                }else if(defaultSpaceFix!=null){
                    //模板停用单位自定义的情况的情况
                    spa.put("spaceId",defaultSpaceFix.getSpaceId());
                    spa.put("spaceName",defaultSpaceFix.getSpaceName());
                    spa.put("iconUrl",defaultSpaceFix.getSpaceIcon());
                    spa.put("spacePath",defaultSpaceFix.getSpacePath());
                    spa.put("spaceType",defaultSpaceFix.getSpaceType());
                }
                data.add(spa);
            }
            Map<String, Object> result = new HashMap<String, Object>();
            result.put("data", data);
            return result;
        }
	}

	/**
     * 空间获取数据
     * @param params
     * params.path:空间URL
     * params.showSp:是否显示栏目属性
     * @return
     * {
     *        "id": "0",
     *        "defaultspace": "0",
     *        "decoration": "D2-M_5-5_T",
     *        "showState": "",
     *        "editKeyId": "-8512990269246714869",
     *        "toDefault": "",
     *        "canusemenu": "",
     *        "sysMenuTree": "",
     *        "spacename": "test",
     *        "pageName": "0",
     *        "path": Constants.spacePreffix+"/personal_custom/default-page.psml",
     *        "canmanage_txt": "<点击此处选择人员>",
     *        "canmanage": "",
     *        "canshare_txt": "战斗部",
     *        "canshare": "Department|-4456351833035881726",
     *        "canpush": null,
     *        "canpersonal": "0",
     *        "state1": "0",
     *        "state2": null,
     *        "sortId": "100",
     *        "spaceIcon": "",
     *        "spaceIconUpload": "",
     *        "spacePubinfoEnable": null,
     *        "spaceMenuEnable": null,
     *        "state": "0"
     *     }
     * @throws Exception
     */
    @POST
    @Path("space")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "空间获取数据", scenes = "M3：空间获取数据")
    public Response getSpace(Map<String, String> params) throws Exception {
        if (!(AppContext.hasPlugin("m3") || AppContext.hasPlugin("weixin"))) {
            return fail(ResourceUtil.getString("common.no.rest.label"));
        }
        String result;
        try {
//            User user = AppContext.getCurrentUser();
//            if (login_useragent_from.pc.name().equals(user.getUserAgentFrom()) 
//                    || login_useragent_from.vjoin.name().equals(user.getUserAgentFrom()) 
//                    || "weixin".equals(user.getUserAgentFrom())) {
//                user.setUserAgentFrom(login_useragent_from.wechat.name());
//            }
            User user = AppContext.getCurrentUser();
            if (login_useragent_from.pc.name().equals(user.getUserAgentFrom()) 
                    || login_useragent_from.vjoin.name().equals(user.getUserAgentFrom()) 
                    || "weixin".equals(user.getUserAgentFrom())) {
                SectionUtils.markMSection();
            }
            result = getMobilePortalManager().getSpace(params);
        } finally {
            SectionUtils.clearMSection();
        }
        return ok(result);
    }

    /**
     * 栏目获取数据
     * @param params
     * params.sectionBeanId: 栏目sectionId
     * params.entityId: 栏目Id
     * params.ordinal: 第几个栏目
     * params.spaceType: 空间类型
     * params.spaceId: 空间ID
     * params.ownerId: 空间所属ID
     * params.x: 栏目x坐标
     * params.y: 栏目y坐标
     * params.width: 栏目宽度
     * params.panelId: 栏目ID
     * @return
     * {
     * "preference" : {
    * "panelId" : "null",
    * "pageLoad" : "null",
    * "spaceType" : "35",
    * "sections_style" : null,
    * "entityId" : "8895914059731124852",
    * "isNarrow" : "false",
    * "sections" : "templeteSection",
    * "sectionWidth" : null,
    * "spaceId" : "-5823220355929849511",
    * "rf" : null,
    * "cityName" : null,
    * "x" : "4",
    * "width" : "10",
    * "y" : "0",
    * "ordinal" : "0"
    * },
    * "Data" : {
    * "bottomButtons" : null,
    *  "moreButton" : null,
    * "dataNum" : 0,
    * "refreshSpaceId" : "",
    * "refreshSpacePath" : "",
    * "showBottomButton" : true,
    * "showChangeButton" : false,
    * "pageNo" : 0,
    * "panels" : null,
    * "sectionResources" : null,
    * "moreLink" : "/xxx/m3/apps/v5/collaboration/html/templateIndex.html?VJoinOpen=VJoin&r=1536139202904",
    * "rows" : [ {
    * "subject" : "就业情况调查表001",
    * "link" : "/xxx/m3/apps/v5/collaboration/html/newCollaboration.html?VJoinOpen=VJoin&templateId=-1704849550646033338&r=1536139202904",
    * "hasAttachments" : null,
    * "bodyType" : null,
    * "createDate" : null,
    * "createMember" : null,
    * "category" : null,
    * "state" : null,
    * "icon" : null,
    * "readFlag" : "false",
    * "createMemberId" : null,
    *  "overTime" : false,
    * "top" : false
    * } ],
    * "resolveFunction" : "mListTemplete"
    * },
  	*  "Name" : "我的模板"
  	* }
    * @throws Exception
    */
    @POST
    @Path("projection")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "栏目获取数据", scenes = "M3：栏目获取数据")
    public Response doProjection(Map<String, Object> params) throws Exception {
        Map<String, Object> map;
        try {
            User user = AppContext.getCurrentUser();
            log.info("userAgentFrom:" + user.getUserAgentFrom());
            if (login_useragent_from.pc.name().equals(user.getUserAgentFrom())
                    || login_useragent_from.vjoin.name().equals(user.getUserAgentFrom())
                    || "weixin".equals(user.getUserAgentFrom())) {
                log.info("if true userAgentFrom:" + user.getUserAgentFrom());
                SectionUtils.markMSection();
            }
            log.info("getSectionManager().doProjection(params)----");
            map = getSectionManager().doProjection(params);
            log.info("doProjection:" + map);
            return ok(map);
        } catch (Exception e){
            log.error("doProjection:" + e.getMessage());
        }finally {
            SectionUtils.clearMSection();
        }
        return null;
    }
    
    /**
     * 根据城市名称获取天气信息
     * @param mCityname
     * @return
     * @throws Exception
     */
    @POST
    @Path("weatherInfo")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "根据城市名称获取天气信息", scenes = "M3：根据城市名称获取天气信息")
    public Response weatherInfo(Map<String, String> params) throws Exception {
    	String mCityname = params.get("cityName");
    	Map<String, String> map = new HashMap<String, String>();
		Weather weather = getWeatherAreaInfoManager().getWeatherByCityName(mCityname);
		if(null != weather) {
			map.put("cityName", weather.getCityName());
			map.put("weather", weather.getWeather());
			map.put("temperature", weather.getTemperature());
			map.put("weatherIcon", weather.getWeatherIcon());
		} else {
			map.put("cityName", "--");
			map.put("weather", "--");
			map.put("temperature", "--");
			map.put("weatherIcon", "");
		}
    	return ok(map);
    }
    
    /**
     * 保存图片横幅栏目的图片设置
     * @param map
     * * <pre>
     * params:{
     * spaceId:空间ID
     * fragmentId:portletId
     * tabIndex: 移动端传0即可
     * bannerImageDataJson:图片横幅json数据:[{"bannerImageId":"2579951699532138186","bannerImageTitle":"","bannerImageUrl":""},{"bannerImageId":"-5276625118072061159","bannerImageTitle":"","bannerImageUrl":""}]
     * }
     * </pre>
     * @return
     */
    @POST
    @Path("saveBannerImage")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "保存图片横幅栏目的图片设置", scenes = "M3：保存图片横幅栏目的图片设置")
    public Response saveBannerImage(Map<String, String> map) {
    	String spaceId= map.get("spaceId");
    	String fragmentId= map.get("fragmentId");
    	String tabIndex= map.get("tabIndex");
    	String bannerImageDataJson= map.get("bannerImageDataJson");
    	String fromTopColumn= map.get("fromTopColumn");
        try {
        	boolean isTopColumn= false;
        	if(Strings.isNotBlank(fromTopColumn) && "true".equals(fromTopColumn)){
        		isTopColumn= true;
        	}
        	boolean permission = false;
        	if(isTopColumn){
        		Long portalId= Long.parseLong(fragmentId);
        		permission = getPortalManager().isPortalAdministrator(AppContext.getCurrentUser(), portalId);
        	}else{
        		permission = getSpaceManager().isSpaceManager(spaceId);
        	}
            if(permission){
            	Long portletId= Long.parseLong(fragmentId);
            	Map<String, String> properties = getPortletEntityPropertyManager().getPropertys(portletId);
            	properties.put("banner_source:"+tabIndex, "source");
                properties.put("source_value:"+tabIndex, bannerImageDataJson);
                //模板5默认情况下是没有存在数据的，前端修改时需要补偿这些数据
                properties.put("sections","bannerImageSection");
                String heightKey = "height:" + tabIndex;
                String heightValue = properties.get(heightKey);
                String columnsNameKey="columnsName:"+tabIndex;
                String columnsNameValue=properties.get(columnsNameKey);
                if(Strings.isBlank(heightValue)){
                    //没有修改过高度取默认的高度200
                	if(isTopColumn){
                		properties.put(heightKey,"200");
                	}else{
                		properties.put(heightKey,"150");
                	}
                }
                if(Strings.isBlank(columnsNameValue)){
                    properties.put(columnsNameKey,ResourceUtil.getString("portal.column.photobanner"));
                }
                getPortletEntityPropertyManager().save(portletId, properties,tabIndex);
//                return success("", "保存成功", 200);
                return success("", "Save successfully", 200);
            }else{
//            	return fail("没有空间管理权限", 500);
            	return fail("No space management privileges", 500);
            }
        } catch (Exception e) {
            log.error("", e);
//            return fail("保存个性化设置失败", 500);
            return fail("Failed to save personalization settings.", 500);
        }
    }

    /**
     * 保存个性化空间设置
     * @param map
     * * <pre>
     * params:{
     * typeId:门户ID/空间ID
     * cKey:空间标识(必填)
     * customizeValue:空间配置的json串
     * }
     * </pre>
     * @return
     */
    @POST
    @Path("saveSpaceCustomize")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @Deprecated
    @ApiOperation(name = "保存个性化空间设置", scenes = "M3：保存个性化空间设置")
    public Response saveUserSpaceCustomize(Map<String, String> map) {
        Long userId = AppContext.currentUserId();
        String typeId = map.get("typeId");
        String cValue = map.get("customizeValue");
        try {
            CtpCustomize customize = getCustomizeManager().getCustomizeInfo(userId, C_VALUE + typeId);
            if (null == customize) {
                customize = new CtpCustomize();
                customize.setIdIfNew();
                customize.setUserId(userId);
                customize.setCkey(C_VALUE + typeId);
                customize.setCvalue(cValue);
                customize.setCreateDate(new Date());
                customize.setUpdateDate(new Date());
                getCustomizeManager().saveCustomize(customize);
            } else {
                customize.setCvalue(cValue);
                customize.setUpdateDate(new Date());
                getCustomizeManager().updateCustomize(customize);
            }
            
//            return success(JSONUtil.parseJSONString(cValue, List.class), "保存个性化设置成功", 200);
            return success(JSONUtil.parseJSONString(cValue, List.class), "Save Personalized Settings Successfully", 200);
        } catch (Exception e) {
            log.error("Failed to save personalization settings", e);
//            return fail("保存个性化设置失败", 500);
            return fail("Failed to save personalization settings", 500);
        }
    }

    /**
     * 获取个人空间个性化设置备选空间
     * @param map
     * <pre>
     * params:{
     * cKey:空间标识(必填)
     * portalId:门户ID(必填)
     * }
     * </pre>
     * @return
     */
    @SuppressWarnings("unchecked")
    @POST
    @Path("getAlternativeSpace")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @Deprecated
    @ApiOperation(name = "获取个人空间个性化设置备选空间", scenes = "M3：获取个人空间个性化设置备选空间")
    public Response getAlternativeSpace(Map<String, String> map) {
        User user = AppContext.getCurrentUser();
        String portalId = map.get("portalId");
        try {
            CtpCustomize customize = getCustomizeManager().getCustomizeInfo(user.getId(), C_VALUE + portalId);
            List<Map<String, String>> spaces = new ArrayList<Map<String, String>>();
            if (null != customize) {
                String cValue = customize.getCvalue();
                List<Map<String, String>> cValueList = JSONUtil.parseJSONString(cValue, ArrayList.class);
                List<SpaceBO> spaceBos = getPortalCacheManager().getSpaceBoList(user, "mobile", portalId);
                //获取未选择空间
                List<SpaceBO> newSpaces = new ArrayList<SpaceBO>();
                newSpaces.addAll(spaceBos);
                for (Map<String, String> cv : cValueList) {
                    for (Iterator<SpaceBO> newSpace = newSpaces.iterator(); newSpace.hasNext();) {
                        SpaceBO space = newSpace.next();
                        if (cv.get("spaceId").equals(space.getSpaceId())) {
                            newSpace.remove();
                            break;
                        }
                    }
                }
                //拼装数据
                for (SpaceBO spaceBo : newSpaces) {
                    Map<String, String> spa = new HashMap<String, String>();
                    spa.put("spaceId", spaceBo.getSpaceId());
                    spa.put("spaceName", spaceBo.getSpaceName());
                    spa.put("iconUrl", spaceBo.getSpaceIcon());
                    spa.put("spacePath", spaceBo.getSpacePath());
                    spa.put("spaceType", spaceBo.getSpaceType());
                    spaces.add(spa);
                }
            }
            return success(spaces, "", 200);
        } catch (Exception e) {
            log.error("", e);
//            return fail("获取个性化设置失败", 500);
            return fail("Failed to get personalized settings", 500);
        }
    }

    /**
     * 获取个性化所有栏目
     * @return
     * [
     * {"sectionName":"栏目名称1","sectionDisplayName":"栏目显示名称1","properties":{栏目属性1json格式},"sort":"序号1"},
     * {"sectionName":"栏目名称1","sectionDisplayName":"栏目显示名称2","properties":{栏目属性2json格式},"sort":"序号2"}
     * ]
     */
    @GET
    @Path("getAllCustomSection")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "获取个性化所有栏目", scenes = "M3：获取个性化所有栏目")
    public Response getAllCustomSection() {
        List<Map<String, String>> allSectionList = new ArrayList<Map<String,String>>();
        try {
            Map<String, BaseSection> sectionBeans = AppContext.getBeansOfType(BaseSection.class);
            Set<Entry<String, BaseSection>> enities = sectionBeans.entrySet();
            for (Entry<String, BaseSection> entry : enities) {
                BaseSection section = entry.getValue();
                if(section.isAllowMobileCustomSet() && section.isAllowUsed()){
                    Map<String,String> properties = new HashMap<String, String>();
                    String name = null;
                    if (section.isRegistrer()) {
                        name = section.getName(Collections.<String, String> emptyMap());
                        properties = this.getProperties(section, name);
                    }
                    Map<String,String> sectionPro = new HashMap<String, String>();
                    sectionPro.put("sectionName", section.getId());
                    sectionPro.put("sectionDisplayName", name);
                    sectionPro.put("properties", JSONUtil.toJSONString(properties));
                    sectionPro.put("sort", section.getSortId()+"");
                    if("pendingEdocSection".equals(section.getId())){
                        //待办公文的处理
                        sectionPro.put("properties",JSONUtil.toJSONString(getMobilePortalManager().generateSPProperties4EdocPending()));
                    }
                    allSectionList.add(sectionPro);
                }
            }
            Collections.sort(allSectionList, new Comparator<Map<String,String>>() {
                @Override
                public int compare(Map<String,String> o1, Map<String,String> o2) {
                    return Integer.parseInt(o1.get("sort")) - Integer.parseInt(o2.get("sort"));
                }
            });
        } catch (Exception e) {
            log.error("", e);
//            return fail("获取所有栏目失败", 500);
            return fail("Failed to get all columns", 500);
        }
//        return success(allSectionList, "获取所有栏目成功", 200);
        return success(allSectionList, "Get all columns successfully", 200);
    }

    /**
     * 根据空间ID获取个性化所选栏目
     * @param map
     * map.spaceId:空间ID
     * @return
     * * [
     * {"sectionName":"栏目名称1","sectionDisplayName":"栏目显示名称1","properties":{栏目属性1json格式},"sort":"序号1"},
     * {"sectionName":"栏目名称1","sectionDisplayName":"栏目显示名称2","properties":{栏目属性2json格式},"sort":"序号2"}
     * ]
     */
    @POST
    @Path("getSelectedSection")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "根据空间ID获取个性化所选栏目", scenes = "M3：根据空间ID获取个性化所选栏目")
    public Response getSelectedSection(Map<String, String> map) {
        String spaceId = map.get("spaceId");
        try {
            List<Map<String, String>> customSections = getPortalCacheManager().getCustomSectionMap(spaceId);
            return success(customSections, "", 200);
        } catch (Exception e) {
            log.error("", e);
//            return fail("获取个性化设置失败", 500);
            return fail("Failure to obtain personalization settings", 500);
        }
    }

    /**
     * 根据门户ID获取门户模板和元素摘要信息
     * @param portalId
     * <pre>
     * params:{
     * portalId:门户ID(必填)
     * }
     * </pre>
     * @return
     * {
     * "code" : 200,
     * "data" : {
     * "msPath" : "/portal/pagelayout/skin_mobile/01.css",
     * "jsPath" : "/portal/pagelayout/layout_mobile/layout01/layout01_01.js",
     * "portalElementTpls" : "[{\"id\":\"portalTop\",\"tpl\":\"tpl-portalTop\"},{\"id\":\"portalSpaceBar\",\"tpl\":\"tpl-spaceBar\"},{\"id\":\"portalFooter\",\"tpl\":\"tpl-portalFooter\"}]",
     * "portalHtml" : "<div id=\"wrapper\" class=\"wrapper\"> \n <div class=\"seeyonElement\" id=\"portalTop\" data-tpl=\"tpl-portalTop\"></div> \n <div id=\"containerWrapper\" class=\"wrapper\"> \n  <div id=\"scroller\" class=\"scroller\"> \n   <div id=\"scrollBack\"> \n    <div class=\"seeyonElement\" id=\"portalSpaceBar\" data-tpl=\"tpl-spaceBar\"></div> \n    <div id=\"columnArea\"></div> \n   </div> \n  </div> \n  <div class=\"portal-contentArea\" id=\"main\"></div> \n </div> \n <div class=\"seeyonElement\" id=\"portalFooter\" data-tpl=\"tpl-portalFooter\"></div> \n</div>",
     * "themeHotspot" : "{\"icon\":{\"iconStyle\":\"1\"},\"main\":{\"tid\":\"1100000001\"},\"portalTop\":{\"mHeaderBgc\":\"#ffffff\",\"mHeaderColor\":\"#000000\"}}",
     * "iconCustomPath" : "",
     * "iconPath" : "/portal/icons/default/fonts/plane/iconfont.css"
     * },
     * "message" : ""
     * }
     * @throws BusinessException 
     */
    @GET
    @Path("getVPortalFrameInfo")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "根据门户ID获取门户模板和元素摘要信息", scenes = "M3：根据门户ID获取门户模板和元素摘要信息")
    public Response getVPortalFrameInfo(@QueryParam("portalId") String portalId,@QueryParam("groupId") Long groupId) throws BusinessException {
        if (!(AppContext.hasPlugin("m3") || AppContext.hasPlugin("weixin"))) {
            return fail(ResourceUtil.getString("common.no.rest.label"));
        }
        
        User user = AppContext.getCurrentUser();
        Long portalLongId= null;
        PortalSet portalSet= null;
        if(Strings.isBlank(portalId)){
        	portalSet= getPortalManager().getMobileMasterPortal(user);
        	if(null!=portalSet){
        		portalLongId= portalSet.getId();
        		portalId= portalLongId.toString();
        	}
            if(!user.isV5Member()){
                //vjoin
                portalId="-1";
            }
        }else{
        	portalLongId= Long.parseLong(portalId);
        	portalSet= getPortalCacheManager().getPortalSetFromCache(portalLongId);
        }
        boolean isFromZxGroupSpace=false;
        if(groupId!=null && String.valueOf(Constants.MOBILE_ZX_GROUP_PORTAL_ID).equals(portalId.toString())){
            isFromZxGroupSpace=true;
        }
        String themeIdStr = getPortalCacheManager().getDefaultThemeByCache(portalId,true);
        if(Strings.isBlank(themeIdStr)){
            if (!user.isV5Member()) {//V-Join
                themeIdStr= "2100000010";
            } else {
                themeIdStr= "2100000001";
            }
        }
        Long themeId = Long.parseLong(themeIdStr);
        PortalTheme theme = getPortalCacheManager().getPortalTheme(themeId,portalLongId);//查询主题信息
        if(null==theme || theme.getType()!=1){ 
        	themeId= 2100000001L;
        	theme =getPortalCacheManager().getPortalTheme(themeId,portalLongId);//查询主题信息
        }
        Long tid = theme.getTid();
        Long skinSetId= theme.getSkinSetId();
        log.info("skinSetId:="+skinSetId);
        String msPath= "";
        String ssPath= "";
        Long msId= theme.getMsid(); 
        Long ssId= theme.getSsid();
        log.info("msId:="+msId);
        log.info("ssId:="+ssId);
        PortalSkinSet skinSet= getPortalCacheManager().getPortalSetSkinById(skinSetId);
        log.info("skinSet:="+skinSet);
        if(null==ssId || ssId==-1){//兼容老数据
        	ssId= skinSet.getSsid();
        }
        if(null==msId){
        	msId= skinSet.getMsid();
        }
        if(null!=msId){
    		PortalSkin msSkin= getPortalCacheManager().getPortalSkinById(msId);
    		if(null!=msSkin){
    			msPath= msSkin.getPath();
    		}
		}
        if(null==ssId || ssId==-1){//兼容下老数据
        	if(themeId.equals(2100000001L)){
        		ssId= 3500000001L;
        	}else if(themeId.equals(2100000002L)){
        		ssId= 3500000002L;
        	}else{
        		ssId= 3500000001L;
        	}
        }
        log.info("ssId:="+ssId);
		if(null!=ssId){
			PortalSkin ssSkin= getPortalCacheManager().getPortalSkinById(ssId);
    		if(null!=ssSkin){
    			ssPath= ssSkin.getPath();
    		}
		}
        
        PortalTemplate pageLayout= getPortalCacheManager().getPortalTemplate(tid);
        String jsPath= pageLayout.getJsPath();
        String cssPath= pageLayout.getCssPath();
        Map<String, Object> vPortalFrameInfo = new HashMap<String, Object>();
        vPortalFrameInfo.put("portalId", portalId);
        vPortalFrameInfo.put("msPath", msPath);
        vPortalFrameInfo.put("ssPath", ssPath);
        vPortalFrameInfo.put("jsPath", jsPath);
        vPortalFrameInfo.put("cssPath", cssPath);
        String iconPath= "";
        String iconCustomPath= "";
        String styleType= "line";
        Map<String,Object> hotspot= getPortalThemeManager().getThemeHotspotForMap(theme,portalLongId,skinSetId,AppContext.currentUserId(),AppContext.currentAccountId());
		if(hotspot!=null){
			vPortalFrameInfo.put("themeHotspot", JSONUtil.toJSONString(hotspot));
			Object icon=hotspot.get("icon");
	    	String styleId= "0";
	    	if(null!=icon){
	    		Map<String,String> map=(Map<String,String>)icon;
	    		styleId=map.get("iconStyle");
	    	}
	    	if(Strings.isBlank(styleId)){
	    		styleId= "0";
	    	}
	    	if("1".equals(styleId)){
	    		styleType= "plane";
	    	}
	    	PortalIconStyle file = portalCacheManager.getPortalIconStyleFromCache(Long.parseLong(styleId));
	    	if(file != null && null!=file.getModifiedCssId()){
	    		V3XFile f = getFileManager().getV3XFile(file.getModifiedCssId());
	            if(f!=null){
	            	Date createDate = f.getCreateDate();
	                CtpFile file1 = this.fileManager.getFile(file.getModifiedCssId(), createDate);
	                if(null!=file1 && file1.exists()){
	                	iconCustomPath= PortalCssEngine.getIconUrl(file);
	                }
	            }
	    	}
		}else{
			vPortalFrameInfo.put("themeHotspot", "{}");
		}
		iconPath= "/portal/icons/default/fonts/"+styleType+"/iconfont.css";
		vPortalFrameInfo.put("iconPath", iconPath);//默认图标
        vPortalFrameInfo.put("iconCustomPath", iconCustomPath);//自定义后的图标样式
        Map<String, Object> map = new HashMap<String, Object>();
        User currentUser = AppContext.getCurrentUser();
        Long memberId = NumberUtils.toLong(currentUser.getId().toString());
        V3xOrgMember member =getOrgManager().getMemberById(memberId);
        V3xOrgDepartment dept = getOrgManager().getDepartmentById(member.getOrgDepartmentId());
        map.put("i",member.getId()==null?"":member.getId().toString());
        map.put("n",OrgHelper.showMemberName(member.getId()));
        map.put("img",OrgHelper.getAvatarImageUrl(member.getId()));
        if(dept!=null){
            map.put("dN",dept.getName());
        }
        int ext = member.getExternalType();
        V3xOrgPost postById = getOrgManager().getPostById(member.getOrgPostId());
        String pN="";
        if(OrgConstants.ExternalType.Inner.ordinal() == ext){
            if(postById!=null){
                pN=postById.getName();
            }else{
                pN=OrgHelper.getExtMemberPriPost(member);
            }
        }else{
            if(postById!=null){
                pN=postById.getName();
            }

        }
        map.put("pN",pN);
        String pageLayoutHtmlContent = getPortalCacheManager().getPageLayoutHtmlContent(tid);
        String datatplJsArr = getPortalCacheManager().getPortaLayoutDataTpls(tid);
        vPortalFrameInfo.put("portalHtml", pageLayoutHtmlContent);
        vPortalFrameInfo.put("portalElementTpls", datatplJsArr);
        
        //返回当前人员信息
        //User currentUser= AppContext.getCurrentUser();
        vPortalFrameInfo.put("portalElementTpls", datatplJsArr);
        vPortalFrameInfo.put("currentUser",JSONUtil.toJSONString(map));
        if(portalSet!=null){
            vPortalFrameInfo.put("portalName", ResourceUtil.getString(portalSet.getPortalName()));
            if(getPortalManager().isMobileMasterPortal(portalSet)){
                vPortalFrameInfo.put("masterPortal","1");
            }else {
                vPortalFrameInfo.put("masterPortal","0");
            }
        }
        Integer sysinit=null;
        if(theme!=null){
            sysinit = theme.getSysinit();
        }
        vPortalFrameInfo.put("sysinitPortal",sysinit==null?"0":sysinit.toString());
        String headColumnInfoId= portalId;
    	String groupChoose= portalCacheManager.getPortalGlobalConfigFromCache("2_"+PortalConstants.USER_CHOOSE_THEME, OrgConstants.GROUPID,OrgConstants.GROUPID);
    	String groupEdit= portalCacheManager.getPortalGlobalConfigFromCache("2_"+PortalConstants.USER_EDIT_THEME, OrgConstants.GROUPID,OrgConstants.GROUPID);
    	if("1".equals(groupEdit)){
    		groupChoose= groupEdit;
    	} 
    	if("0".equals(groupChoose) && portalManager.isMobileMasterPortal(portalSet)){
    		headColumnInfoId= "2";
    	}
        Map<String,Object> headColumnElementData= null;
        if(theme!=null){
            Long themeIdGet = theme.getId();
            if(themeIdGet!=null){
                headColumnElementData= getMobilePortalManager().getPortalHeadColumnElementData(headColumnInfoId,String.valueOf(themeIdGet));
            }
        }
        vPortalFrameInfo.put("headColumnInfo", headColumnElementData);
        String spaceCategory = "mobile";
        Map<String, Object> spaceList=new HashMap<String,Object>();
        if(!isFromZxGroupSpace){
            spaceList= getSpacesInner(spaceCategory, portalId);
        }else {
            PortalSpaceFix zxGroupSpace = this.getMobilePortalManager().getZxGroupSpace(groupId.toString());//分组绑定的空间
            if(zxGroupSpace!=null){
                List<Map<String, String>> data = new ArrayList<Map<String, String>>();
                Map<String, String> spa = new HashMap<String, String>();
                spa.put("spaceId", zxGroupSpace.getId().toString());
                spa.put("spaceName", ResourceUtil.getString(zxGroupSpace.getSpacename()));
                spa.put("iconUrl", zxGroupSpace.getSpaceIcon());
                spa.put("spacePath", zxGroupSpace.getPath());
                spa.put("spaceType", zxGroupSpace.getType().toString());
                data.add(spa);
                spaceList.put("data",data);
            }
        }
        boolean hasMiddleOrTopNav=false;
        if (user.isV5Member() && datatplJsArr != null && (datatplJsArr.contains("navBar") || datatplJsArr.contains("topNav"))) {
            hasMiddleOrTopNav = true;
        }
        String mTopOrMiddleNavFirstSpaceId=null;
        if(hasMiddleOrTopNav==true){
            PortalNav userMobileNavCommon = getPortalNavManager().getCurrentUserMobileNavFront(portalId.toString(), "mTopOrMiddleNav");//中上导航
            if(userMobileNavCommon!=null){
                List<PortalNavBo> navBoList = userMobileNavCommon.getPortalNavBoList();
                if(navBoList!=null&&navBoList.size()>0){
                    //有中上导航取的是门户上中导航中排最左边有权限的本门户空间
                    for(PortalNavBo portalNavBo:navBoList){
                        String navType = portalNavBo.getNavType();
                        String isDelete = portalNavBo.getIsDelete();
                        if("space".equals(navType) && !"1".equals(isDelete)){
                            String tempAllIds = portalNavBo.getAllIds();
                            if(tempAllIds.contains(portalId)){
                                mTopOrMiddleNavFirstSpaceId=portalNavBo.getId();//本门户下第一个有权限的空间
                                break;
                            }
                        }
                    }
                }
            }

        }
        if(mTopOrMiddleNavFirstSpaceId!=null){
            List<SpaceBO> spaces = portalCacheManager.getSpaceBoList(AppContext.getCurrentUser(),"mobile", portalId);
            if(mTopOrMiddleNavFirstSpaceId!=null) {
                for (SpaceBO spaceBO : spaces) {
                    if (spaceBO != null && mTopOrMiddleNavFirstSpaceId.equals(spaceBO.getParentId())) {
                        mTopOrMiddleNavFirstSpaceId = spaceBO.getSpaceId();
                        break;
                    }
                }
            }
            Object data = spaceList.get("data");
            if(data instanceof List){
                List<Map<String, String>> mapList = (List<Map<String, String>>) data;
                int mTopOrMiddleNavFirstSpaceIdIndex=-1;
                for(int index=0;index<mapList.size();index++){
                    Map<String, String> spaceMap = mapList.get(index);
                    String spaceId = spaceMap.get("spaceId");
                    if(mTopOrMiddleNavFirstSpaceId.equals(spaceId)){
                        mTopOrMiddleNavFirstSpaceIdIndex=index;
                        break;
                    }
                }
                if(mTopOrMiddleNavFirstSpaceIdIndex!=-1&&mTopOrMiddleNavFirstSpaceIdIndex!=0){
                    Collections.swap(mapList,0,mTopOrMiddleNavFirstSpaceIdIndex);
                }
                if(getPortalManager().isMobileMasterPortal(portalSet)){
                    //主门户时获取有权限的集团自定义空间
                    List<SpaceBO> groupSpaces = portalCacheManager.getSpaceBoList(AppContext.getCurrentUser(),"mobile","2");
                    List<SpaceBO> userSpaces = portalCacheManager.getSpaceBoList(AppContext.getCurrentUser(),"mobile");
                    Map<String, SpaceBO> parentKeyMap = userSpaces.stream().collect(Collectors.toMap(SpaceBO::getParentId, Function.identity(), (e1, e2) -> e1));
                    if(CollectionUtils.isNotEmpty(groupSpaces)){
                        for (SpaceBO groupSpace : groupSpaces) {
                            String spaceType = groupSpace.getSpaceType();
                            if("36".equals(spaceType)){
                                //集团自定义空间
                                Map<String, String> spa = new HashMap<String, String>();
                                spa.put("spaceId", groupSpace.getSpaceId());
                                spa.put("spaceName", groupSpace.getSpaceName());
                                spa.put("iconUrl", groupSpace.getSpaceIcon());
                                spa.put("spacePath", groupSpace.getSpacePath());
                                spa.put("spaceType", groupSpace.getSpaceType());
                                mapList.add(spa);
                                if (Objects.nonNull(parentKeyMap.get(groupSpace.getSpaceId()))) {
                                    SpaceBO spaceBO = parentKeyMap.get(groupSpace.getSpaceId());
                                    Map<String, String> spaceData = new HashMap<String, String>();
                                    spaceData.put("spaceId", spaceBO.getSpaceId());
                                    spaceData.put("spaceName", spaceBO.getSpaceName());
                                    spaceData.put("iconUrl", spaceBO.getSpaceIcon());
                                    spaceData.put("spacePath", spaceBO.getSpacePath());
                                    spaceData.put("spaceType", spaceBO.getSpaceType());
                                    mapList.add(spaceData);
                                }
                            }
                        }
                    }
                }
            }
        }
        sortSpaceList(spaceList);
        vPortalFrameInfo.put("spaceList", spaceList);
        vPortalFrameInfo.put("serverStartupVersion", SystemEnvironment.getServerStartTime());
        String weatherLocationUrl = SystemProperties.getInstance().getProperty("portal.weather.locationUrl");
        vPortalFrameInfo.put("weatherLocationUrl", weatherLocationUrl);
        if(isFromZxGroupSpace){
            //致信轻协作空间展示，写死的
            String zxThemeHotspot="{\n" +
                    "        \"icon\":{\n" +
                    "          \"iconStyle\":\"0\"\n" +
                    "        },\n" +
                    "        \"report\":{\n" +
                    "          \"reportTheme\":\"1\"\n" +
                    "        },\n" +
                    "        \"skin\":{\n" +
                    "          \"mWrapperBgc\":\"#f8f9fb\",\n" +
                    "          \"mWrapperBgi\":\"\",\n" +
                    "          \"mHeaderColor\":\"#000000\",\n" +
                    "          \"mHeaderBgc\":\"#ffffff\",\n" +
                    "          \"mNavBarColor\":\"rgba(255,255,255,0.8)\",\n" +
                    "          \"mNavBarBgc\":\"rgba(0,0,0,0.1)\",\n" +
                    "          \"mNavBarSc\":\"#fff\",\n" +
                    "          \"mColumnAreaBgc\":\"\",\n" +
                    "          \"mColumnAreaBgi\":\"\",\n" +
                    "          \"scrollBgi\":\"0\",\n" +
                    "          \"cssPath\":\"6592531903391549862\"\n" +
                    "        },\n" +
                    "        \"main\":{\n" +
                    "          \"tid\":\"1100000001\",\n" +
                    "          \"ssid\":\"3500000001\",\n" +
                    "          \"msid\":\"3100000001\",\n" +
                    "          \"csid\":\"-1\",\n" +
                    "          \"iconid\":\"1\",\n" +
                    "          \"echartStyleId\":\"1\",\n" +
                    "          \"preview\":\"/portal/images/themes/theme_mobile_01.png\"\n" +
                    "        },\n" +
                    "        \"section\":{\n" +
                    "          \"sectionPanelBorderRadius\":\"0\",\"sectionPanelBgc\":\"transparent\"\n" +
                    "        },\n" +
                    "        \"base\":{\n" +
                    "          \"showFooterNav\":\"0\"\n" +
                    "        }" +
                    "}";
            vPortalFrameInfo.put("cssPath","/portal/pagelayout/layout_mobile/layout01/layout01_01.css");
            vPortalFrameInfo.put("msPath","/portal/pagelayout/skin_mobile/01.css");
            vPortalFrameInfo.put("ssPath","/portal/sections/skin_mobile/01.css");
            vPortalFrameInfo.put("jsPath","/portal/pagelayout/layout_mobile/layout01/layout01_01.js");
            vPortalFrameInfo.put("themeHotspot",zxThemeHotspot);

        }
        return success(vPortalFrameInfo, "", 200);
    }

    /**
     * 根据主题ID获取幻灯片数据
     * @param portalId
     * <pre>
     * params:{
     *  portalId:门户ID(必填)
     * }
     * </pre>
     * @return
     * @throws BusinessException 
     */
    @GET
    @Path("slide")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "根据主题ID获取幻灯片数据", scenes = "M3：根据主题ID获取幻灯片数据")
    public Response getSlide(@QueryParam("portalId") String portalId) {
    	try {
        	String themeIdStr=getPortalCacheManager().getDefaultThemeByCache(portalId,true);
        	SlideVPortalPO slide= getSlideVPortalManager().getSlideByPortalId(themeIdStr,portalId);
            return success(slide.getValue(), "", 200);
		} catch (Exception e) {
			this.log.error("",e);
			return success(null, "", 500);
		}
    }
    
    /**
     * 根据entityId获取头部栏目属性数据
     * @param entityId
     * <pre>
     * params:{
     *  entityId:门户ID(必填)
     * }
     * </pre>
     * @return
     * @throws BusinessException 
     */
    @GET
    @Path("topIncludeColumn")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "根据entityId获取头部栏目属性数据", scenes = "M3：根据entityId获取头部栏目属性数据")
    public Response getTopIncludeColumnDataObj(@QueryParam("entityId") String entityId) {
    	try {
    		Map<String,Object> headColumnElementData= getMobilePortalManager().getPortalHeadColumnElementData(entityId);
    		
            return success(headColumnElementData, "", 200);
		} catch (Exception e) {
			this.log.error("",e);
			return success(null, "", 500);
		}
    }

    public SlideVPortalManager getSlideVPortalManager() {
        if (slideVPortalManager == null) {
            slideVPortalManager = (SlideVPortalManager) AppContext.getBean("slideVPortalManager");
        }
        return slideVPortalManager;
    }

	public PortalThemeManager getPortalThemeManager() {
		if (portalThemeManager == null) {
			portalThemeManager = (PortalThemeManager) AppContext.getBean("portalThemeManager");
        }
        return portalThemeManager;
    }
    /**
     * 保存个性化空间栏目
     * @return
     */
    @SuppressWarnings("unchecked")
    @POST
    @Path("saveCustomSpace")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @Deprecated
    @ApiOperation(name = "保存个性化空间栏目", scenes = "M3：保存个性化空间栏目")
    public Response saveCustomSpace(Map<String,Object> params){
        try {
            String portalId = params.get("portalId").toString();
            String spaceId = params.get("spaceId").toString();
            String groupId = MapUtils.getString(params, "groupId", null);
            PortalSpaceFix space = getSpaceManager().getSpaceFix(Long.parseLong(spaceId));
            String isNew = "modify";
            if (null == space.getParentId()) {
                isNew = "new";
            }
            String spaceName = "space.default.m3mobile_custom.label";
            Integer spaceCategory = SpaceType.m3mobile_custom.ordinal();
            if (SpaceType.m3mobile_leader.ordinal()==space.getType()) {
                spaceCategory = SpaceType.m3mobile_leader_custom.ordinal();
            }
            String path = space.getPath();
            List<Map<String, Object>> fragmentList = (List<Map<String, Object>>)params.get("fragments");
            boolean isRealCustome=true;
            try{
                if(null==space.getParentId()){
                    /**
                     * 传递过来的是模板Id，需要进行数据对比判断用户是否进行了自定义，对比依据为
                     * x，y及sectionUUIDS
                     */
                    String portletJsonStr = getMobilePortalManager().getSpace(path, "show");
                    Map<String,Object> portletMap = JSONUtil.parseJSONString(portletJsonStr, Map.class);
                    Object portlets = portletMap.get("portlets");
                    if(portlets instanceof List){
                        List<Map<String, Object>> portletsList = (List<Map<String, Object>>) portlets;
                        if(CollectionUtils.isNotEmpty(portletsList)&&CollectionUtils.isNotEmpty(fragmentList)&&portletsList.size()==fragmentList.size()){
                            List<String> portletKeyList=new ArrayList<String>(portletsList.size());
                            for(Map<String,Object> portletItemMap:portletsList){
                                String x = ParamUtil.getString(portletItemMap, "x","-1");
                                String y = ParamUtil.getString(portletItemMap, "y","-1");
                                StringBuffer buffer=new StringBuffer(x);
                                buffer.append("_").append(y);
                                Object itemsObj = portletItemMap.get("items");
                                if(itemsObj instanceof List){
                                    List<Map<String, Object>> itemsList = (List<Map<String, Object>>) itemsObj;
                                    if(CollectionUtils.isNotEmpty(itemsList)){
                                        Map<String, Object> itemObjectMap = itemsList.get(0);
                                        Object spMapObj = itemObjectMap.get("SP");
                                        if(spMapObj instanceof Map){
                                            Map<String, Object> mapObj = (Map<String, Object>) spMapObj;
                                            String sectionUUIDs = ParamUtil.getString(mapObj, "sectionUUIDs","-1");
                                            buffer.append("_").append(sectionUUIDs);
                                        }
                                        portletKeyList.add(buffer.toString());
                                    }
                                }
                            }

                            List<String> customKeyList=new ArrayList<String>(fragmentList.size());
                            for(Map<String,Object> map:fragmentList){
                                String x = ParamUtil.getString(map, "x","-1");
                                String y = ParamUtil.getString(map, "y","-1");
                                StringBuffer buffer=new StringBuffer(x);
                                buffer.append("_").append(y);
                                Object properties = map.get("properties");
                                if(properties instanceof Map){
                                    Map<String, Object> propertiesMap = (Map<String, Object>) properties;
                                    String sectionUUIDs = ParamUtil.getString(propertiesMap, "sectionUUIDs","-1");
                                    buffer.append("_").append(sectionUUIDs);
                                }
                                customKeyList.add(buffer.toString());
                            }
                            boolean equalCollection = CollectionUtils.isEqualCollection(portletKeyList, customKeyList);
                            if(equalCollection){
                                //完全相同未自定义不需要产生数据
                                isRealCustome=false;
                            }
                        }
                    }

                }
            }
            catch (Exception e){
//                log.error("自定义空间栏目对比出错！",e);
                log.error("Error comparing custom space columns!",e);
            }
            if(!isRealCustome && Strings.isBlank(groupId)){
                return success(path,"",200);
            }
            //封装基础数据
            Map<String,Object> basicParam = new HashMap<String, Object>();
            basicParam.put("isNew", isNew);
            basicParam.put("spaceId", spaceId);
            basicParam.put("spaceName", spaceName);
            basicParam.put("spaceType", spaceCategory+"");
            basicParam.put("spaceEnable", true);
            basicParam.put("spaceCategory", "mobile");
            basicParam.put("canPersonal", "1");
            basicParam.put("canPush", "0");
            
            Map<String,Object> map = new HashMap<String, Object>();
            map.put("basicParam", basicParam);
            map.put("path", path);
            map.put("portalId", portalId);
            map.put("fragments", fragmentList);
            if(isRealCustome){
                //个性化时才产生新空间
                map.put("commonUser", "commonUser");
            }
            if(Strings.isNotEmpty(groupId) && Strings.isLong(spaceId)){
                //来着致信轻协作
                boolean managerOfThisSpace = this.getSpaceManager().isManagerOfThisSpace(AppContext.currentUserId(), Long.valueOf(spaceId));
                PortalSpaceFix spaceFix = this.getSpaceManager().getSpaceFix(Long.valueOf(spaceId));
                if(!managerOfThisSpace && spaceFix!=null && spaceFix.getType()!=null && spaceFix.getType()!= SpaceType.m3mobile_zx_group.ordinal()){
                    log.error("管理权限被取消或者空间已经删除!");
                    return fail(ResourceUtil.getString("space.notExist.label"), 500);
                }else if(spaceFix!=null && spaceFix.getType()!=null && spaceFix.getType()== SpaceType.m3mobile_zx_group.ordinal()){
                    boolean canMangerZxGroupSpace = this.getMobilePortalManager().canMangerZxGroupSpace(spaceFix);
                    if(!canMangerZxGroupSpace){
                        log.error("管理权限被取消或者空间已经删除!");
                        return fail(ResourceUtil.getString("space.notExist.label"), 500);
                    }
                }
                    isRealCustome=false;
                    isNew="modify";
                    this.getMobilePortalManager().updateSpaceOnlySections(map);
                    return success(path,"",200);
            }
            String currentSpaceId = this.getMobilePortalManager().saveSpace(map);
            PortalSpaceFix psf = this.getSpaceManager().getSpaceFix(Long.parseLong(currentSpaceId));
            //新建的空间保存到个性化中
            if ("new".equals(isNew)) {
                /** 将数据追加到个性化设置中 start **/
                User user = AppContext.getCurrentUser();
                //新空间封装到Map中
                Map<String,String> spaceMap = new HashMap<String, String>();
                List<Map<String,String>> cValueList = new ArrayList<Map<String,String>>();
                spaceMap.put("spaceId", psf.getId()+"");
                spaceMap.put("spaceName", psf.getSpacename());
                spaceMap.put("iconUrl", psf.getSpaceIcon());
                spaceMap.put("spacePath", psf.getPath());
                spaceMap.put("spaceType", psf.getType()+"");
                
                CtpCustomize customize = getCustomizeManager().getCustomizeInfo(user.getId(), C_VALUE + portalId);
                
                if (null == customize) {
                    cValueList.add(spaceMap);
                    customize = new CtpCustomize();
                    customize.setIdIfNew();
                    customize.setUserId(user.getId());
                    customize.setCkey(C_VALUE + portalId);
                    customize.setCvalue(JSONUtil.toJSONString(cValueList));
                    customize.setCreateDate(new Date());
                    customize.setUpdateDate(new Date());
                    getCustomizeManager().saveCustomize(customize);
                } else {
                    String cValue = customize.getCvalue();
                    cValueList = JSONUtil.parseJSONString(cValue, ArrayList.class);
                    cValueList.add(spaceMap);
                    customize.setCvalue(JSONUtil.toJSONString(cValueList));
                    customize.setUpdateDate(new Date());
                    getCustomizeManager().updateCustomize(customize);
                }
                /** 将数据追加到个性化设置中 end **/
            }
            
            return success(psf.getPath(),"",200);
        } catch (Exception e) {
           log.error("",e);
//           return fail("保存个性化空间栏目失败", 500);
           return fail("Failed to save personalized space column", 500);
        }
        
    }
    
    private Map<String,String> getProperties(BaseSection section, String columnsName){
        Map<String,String> result = new HashMap<String, String>();
        result.put("sections", section.getId());
        List<SectionProperty> properties = section.getProperties();
        for(SectionProperty p:properties){
            SectionReference[] reference = p.getReference();
            for(SectionReference r:reference){
                //获取移动端栏目属性
                if (null == r.getSpaceType()) {
                    continue;
                }
                if (!r.getSpaceType().contains("m3mobile")) {
                    continue;
                }
                String defValue = "";
                if (null != r.getmDefaultValue()) {
                    defValue = r.getmDefaultValue();
                } else {
                    defValue = r.getDefaultValue() == null ? "" : r.getDefaultValue();
                }
                result.put(r.getName() + ":0", defValue);
                if (r.getValueTypeEnum() == ValueType.clickText) {
                    SectionReferenceValueRange[] valueRanges = r.getValueRanges();
                    for(SectionReferenceValueRange valueRange:valueRanges) {
                        if (!valueRange.getSpaceType().contains("m3mobile")) {
                            continue;
                        }
                        result.put(valueRange.getValue()+"_name:0", ResourceUtil.getString(r.getSubject()));
                        result.put(valueRange.getValue()+"_value:0", "");
                        if (Strings.isNotBlank(valueRange.getMobileResourcesFunction())) {
                            result.put("resourcesFunction", valueRange.getMobileResourcesFunction());
                        }
                        if (Strings.isNotBlank(valueRange.getMobileStyleFunction())) {
                            result.put("styleFunction", valueRange.getMobileStyleFunction());
                        }
                    }
                }
            }
        }
        return result;
    }
    
    @GET
    @Path("getPortalId/{spaceId}")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @Deprecated
    @ApiOperation(name = "获取空间所属门户", scenes = "M3：获取空间所属门户")
    public Response getPortalId(@PathParam("spaceId") Long spaceId) throws BusinessException{
        Long portalId = portalId = this.getPortalManager().getSpaceBelongedPortalId(spaceId);
        if(portalId == null){
            portalId = -1L;
        }
        return success(portalId + "", "", 200);
    }
    @GET
    @Path("restoreSpace/{spaceId}")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "门户空间恢复默认", scenes = "M3：门户空间恢复默认")
    public Response restoreSpace(@PathParam("spaceId") Long spaceId,@QueryParam("groupId") Long groupId) throws BusinessException{
        try {
            PortalSpaceFix spaceFix = this.getPortalCacheManager().getPageFixIdCacheByKey(spaceId);
            Long entityId = spaceFix.getEntityId();
            Long userId = AppContext.getCurrentUser().getId();
            Long returnSpaceId=spaceId;
            if(spaceFix!=null&&spaceFix.getParentId()!=null&& userId.longValue()==entityId.longValue()){
                //只有是个人的
                this.getSpaceManager().restoreCustomSpaceDefault(spaceFix);
                returnSpaceId=spaceFix.getParentId();
            }
            if(groupId!=null){
                //致信群组过来的管理页面
                this.getMobilePortalManager().restoreMobileAdminSpace(spaceFix);
            }
            List<Map<String, String>> customSections = getPortalCacheManager().getCustomSectionMap(String.valueOf(returnSpaceId));
            List<Map<String, String>> allSectionList = new ArrayList<Map<String,String>>();
            Map<String, BaseSection> sectionBeans = AppContext.getBeansOfType(BaseSection.class);
            Set<Entry<String, BaseSection>> enities = sectionBeans.entrySet();
            for (Entry<String, BaseSection> entry : enities) {
                BaseSection section = entry.getValue();
                if(section.isAllowMobileCustomSet() && section.isAllowUsed()){
                    Map<String,String> properties = new HashMap<String, String>();
                    String name = null;
                    if (section.isRegistrer()) {
                        name = section.getName(Collections.<String, String> emptyMap());
                        properties = this.getProperties(section, name);
                    }
                    Map<String,String> sectionPro = new HashMap<String, String>();
                    sectionPro.put("sectionName", section.getId());
                    sectionPro.put("sectionDisplayName", name);
                    sectionPro.put("properties", JSONUtil.toJSONString(properties));
                    sectionPro.put("sort", section.getSortId()+"");
                    allSectionList.add(sectionPro);
                }
            }
            Collections.sort(allSectionList, new Comparator<Map<String,String>>() {
                @Override
                public int compare(Map<String,String> o1, Map<String,String> o2) {
                    return Integer.parseInt(o1.get("sort")) - Integer.parseInt(o2.get("sort"));
                }
            });
            Map<String,Object> map = new HashMap<String, Object>(3);
            map.put("spaceId",String.valueOf(returnSpaceId));
            map.put("customSections",customSections);
            map.put("allSectionList",allSectionList);
            return success(map, "", 200);
        } catch (BusinessException e) {
            log.error("", e);
            return fail(e.getMessage(), 500);
        }
    }
    @POST
    @Path("transCreateOrBindZxGroupSpace")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "空间与致信群组创建或者绑定", scenes = "M3：空间与致信群组创建或者绑定")
    public Response transCreateOrBindZxGroupSpace(Map<String,Object> params){
        try {
            String groupId = MapUtils.getString(params, "groupId", null);
            String bindSpaceId = MapUtils.getString(params, "bindSpaceId", null);
            getMobilePortalManager().transCreateOrBindZxGroupSpace(groupId,null,bindSpaceId);
            return success("", "", 200);
        } catch (BusinessException e) {
            log.error("", e);
            return fail(e.getMessage(), 500);
        }
    }
    @GET
    @Path("getZxAdminSpaces")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "查找空间", scenes = "M3：查找空间（主要按空间名称和状态查找）")
    public Response getZxAdminSpaces(@QueryParam("groupId") String groupId){
        try {
            List<Map> zxAdminSpaceList = getSpaceManager().getZxAdminSpaceList(groupId);
            return success(zxAdminSpaceList, "", 200);
        } catch (BusinessException e) {
            log.error("", e);
            return fail(e.getMessage(), 500);
        }
    }
    @POST
    @Path("savePortalNav")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "保存个性化导航", scenes = "M3：保存个性化导航")
    public Response saveNav(Map<String,Object> params){
        try{
            String portalId = params.get("portalId").toString();
            List<Map<String,String>> selectedList = (List<Map<String,String>>)params.get("selectedList");
            boolean isRealCustom=true;
            List<String> deleteAllIdsList=new ArrayList<String>();
            PortalNav currentUserTopOrMiddleNavList=getPortalNavManager().getCurrentUserMobileNavFront(portalId.toString(),NavEnum.MOBILE_TopMiddleNav.getKey());
            if(currentUserTopOrMiddleNavList!=null){
                List<PortalNavBo> portalNavBoList = currentUserTopOrMiddleNavList.getPortalNavBoList();
                if(CollectionUtils.isNotEmpty(portalNavBoList)&&CollectionUtils.isNotEmpty(selectedList)){
                    List<String> portalNavsList=new ArrayList<String>();
                    List<String> selectedNavsList=new ArrayList<String>();
                    List<String> oldSelectedAllIdsList=new ArrayList<String>();
                    for(int j=0;j<portalNavBoList.size();j++){
                        PortalNavBo portalNavBo = portalNavBoList.get(j);
                        String allIds = portalNavBo.getAllIds();
                        if(Strings.isBlank(allIds)){
                            allIds="-1";
                        }
                        portalNavsList.add(j+"_"+allIds);
                        oldSelectedAllIdsList.add(allIds);
                    }
                    List<String> selectedAllIds=new ArrayList<String>();
                    for(int i=0;i<selectedList.size();i++){
                        Map<String, String> selectedMap = selectedList.get(i);
                        String allIds = ParamUtil.getString(selectedMap, "allIds", "-1");
                        selectedNavsList.add(i+"_"+allIds);
                        selectedAllIds.add(allIds);
                    }
                    if(CollectionUtils.isEqualCollection(portalNavsList,selectedNavsList)){
                        isRealCustom=false;
                    }
                    for (String oldSelectedAllids : oldSelectedAllIdsList) {
                        if(!selectedAllIds.contains(oldSelectedAllids)){
                            deleteAllIdsList.add(oldSelectedAllids);
                        }
                    }
                }
            }
            if(isRealCustom){
                this.getPortalNavManager().saveMobileCustomNav(portalId, NavEnum.MOBILE_TopMiddleNav,selectedList,deleteAllIdsList);
            }
            if(Strings.isNotBlank(portalId)&&Strings.isDigits(portalId)){
                Map<String, Object> map = getMobilePortalNav(Long.valueOf(portalId));
                return success(map,"",200);
            }
            return success("","",200);
        }catch (Exception e) {
//            log.error("保存个性化导航失败",e);
//            return fail("保存个性化导航失败", 500);
            log.error("Failure to save personalized navigation",e);
            return fail("Failure to save personalized navigation", 500);
        }

    }

    /**
     * 配合小致语音打开门户改造，对于预置的门户，小致无法获取门户Id
     * 需要根据传入的门户类型，根据当前登录人的信息获取对应的门户Id
     * @param type   预置门户的类型 1:工作门户
     * @return
     * @throws BusinessException
     */
    @GET
    @Path("getPresetPortalId/{type}")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(name = "获得门户id及名称", scenes = "小致调用：获得门户id及名称")
    public Response getPresetPortalId(@PathParam("type") String type) throws BusinessException{
        if(Strings.isNotBlank(type)&&Strings.isDigits(type)){
            Map<String,String> portalMap=new HashMap<String, String>(2);
            Integer presetType = Integer.valueOf(type);
            switch (presetType){
                case 1:
                    //工作门户
                    String item= "Mobile_"+PortalConstants.MASTER_PORTAL;
                    long currentAccountId = AppContext.currentAccountId();
                    String mainPortalIdStr= getPortalCacheManager().getPortalGlobalConfigFromCache(item, currentAccountId, currentAccountId);
                    if(Strings.isNotBlank(mainPortalIdStr)&&Strings.isDigits(mainPortalIdStr)){
                        PortalSet portalSetFromCache = getPortalCacheManager().getPortalSetFromCache(Long.valueOf(mainPortalIdStr));
                        if(portalSetFromCache!=null){
                            Long portalId = portalSetFromCache.getId();
                            String portalName=ResourceUtil.getString(portalSetFromCache.getPortalName());
                            portalMap.put("portalId",portalId.toString());
                            portalMap.put("portalName",portalName);
                            return success(portalMap,"",200);
                        }
                    }
                    break;
                default:
                    break;

            }
        }
        return fail("Error", 500);
    }
    @GET
    @Path("resetPortalNav/{portalId}")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @Deprecated
    @ApiOperation(name = "重置门户导航", scenes = "M3：重置门户导航")
    public Response resetPortalNav(@PathParam("portalId") Long portalId) throws BusinessException{
        try {
            this.getPortalNavManager().resetMobileCustomNav(portalId,NavEnum.MOBILE_TopMiddleNav);
            Map<String, List<PortalNavBo>> map = this.getPortalNavManager().getSelectedAndCanSelectMap(portalId, NavEnum.MOBILE_TopMiddleNav);
            return success(map, "", 200);
        } catch (Exception e) {
            log.error("", e);
//            return fail("恢复导航内容出错:" + e.getMessage(), 500);
            return fail("Error recovering navigation content:" + e.getMessage(), 500);
        }
    }
    @GET
    @Path("getSelectedAndCanSelectPortalNav/{portalId}")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @Deprecated
    @ApiOperation(name = "获取可以选择的移动空间导航", scenes = "M3：获取可以选择的移动空间导航")
    public Response getSelectedAndCanSelectPortalNav(@PathParam("portalId") Long portalId) throws BusinessException{
        try {
            Map<String, List<PortalNavBo>> map = this.getPortalNavManager().getSelectedAndCanSelectMap(portalId, NavEnum.MOBILE_TopMiddleNav);
            return success(map, "", 200);
        } catch (Exception e) {
            log.error("", e);
//            return fail("获取移动空间导航出错:" + e.getMessage(), 500);
            return fail("Error in getting mobile space navigation:" + e.getMessage(), 500);
        }
    }
    @GET
    @Path("getPortalNav/{portalId}")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces(MediaType.APPLICATION_JSON)
    @Deprecated
    @ApiOperation(name = "获取移动空间导航", scenes = "M3：获取移动空间导航")
    public Response getPortalNav(@PathParam("portalId") Long portalId) throws BusinessException{
        try {
            Map<String,Object> map=getMobilePortalNav(portalId);
            return success(map, "", 200);
        } catch (Exception e) {
            log.error("", e);
//            return fail("获取移动空间导航出错:" + e.getMessage(), 500);
            return fail("Error in getting mobile space navigation:" + e.getMessage(), 500);
        }
    }
    private Map<String,Object> getMobilePortalNav(Long portalId) throws BusinessException{
        Map<String, Object> map=new HashMap<String,Object>(4);
        String mBottomNav="mBottomNav";
        String mTopOrMiddleNav="mTopOrMiddleNav";
        String mAddNav="mAddNav";
        List<PortalNavBo> bottomNavList=new ArrayList<PortalNavBo>();
        List<PortalNavBo> mTopOrMiddleNavList=new ArrayList<PortalNavBo>();
        List<PortalNavBo> mAddNavList=new ArrayList<PortalNavBo>();

        User user = AppContext.getCurrentUser();
        boolean mTopOrMiddleNavCustomSwitch=false;
        if (!user.isV5Member()) {//V-Join
            Map<String, Object> vjoinSpaceMap = getMobilePortalManager().getSpaceMapByAccess("mobile", AppContext.currentUserId());
            for(String path : vjoinSpaceMap.keySet()){
                Map space = (Map)vjoinSpaceMap.get(path);
                PortalNavBo bo = new PortalNavBo();
                bo.setId(space.get("id").toString());
                bo.setNavName((String)space.get("spaceName"));
                bo.setUrl("spaceId|"+space.get("id").toString());
                mTopOrMiddleNavList.add(bo);
            }
        } else {
            if(portalId == null){
                portalId = -1L;
            }

            PortalNav currentUserMobileNav = getPortalNavManager().getCurrentUserMobileNavFront(portalId.toString(), mBottomNav);
            PortalNav currentUserTopOrMiddleNavList=getPortalNavManager().getCurrentUserMobileNavFront(portalId.toString(), mTopOrMiddleNav);
            PortalNav currentUerAddNavList=getPortalNavManager().getCurrentUserMobileNavFront(portalId.toString(),mAddNav);
            if(currentUserMobileNav!=null){
                bottomNavList = currentUserMobileNav.getPortalNavBoList();
            }
            if(currentUserTopOrMiddleNavList!=null){
                mTopOrMiddleNavList=currentUserTopOrMiddleNavList.getPortalNavBoList();
                if(CollectionUtils.isNotEmpty(mTopOrMiddleNavList)){
                    List<PortalNavBo> realSelectedList= new ArrayList<PortalNavBo>();
                    Set<String> realSelectedSet=new HashSet<String>();
                    if(org.apache.commons.collections.CollectionUtils.isNotEmpty(mTopOrMiddleNavList)){
                        for (PortalNavBo navBo : mTopOrMiddleNavList) {
                            if(navBo !=null){
                                String allIds = navBo.getAllIds();
                                PortalSpaceFix spaceFix = null;
                                PortalSpaceFix realDefaultSpaceFix = null;
                                if(allIds.contains("SpaceAppCategory")){
                                    spaceFix = getSpaceManager().getSpaceFix(Long.parseLong(navBo.getId()));
                                    realDefaultSpaceFix = getSpaceManager().getRealDefaultSpaceFix(spaceFix);
                                }
                                Integer spaceState = 0;
                                if(realDefaultSpaceFix != null){
                                    spaceState = realDefaultSpaceFix.getState();
                                }
                                if(!realSelectedSet.contains(allIds) && !"1".equals(navBo.getIsDelete()) && 0 == spaceState){
                                    //去重，去删除的
                                    realSelectedList.add(navBo);
                                    realSelectedSet.add(allIds);
                                }
                            }
                        }
                        mTopOrMiddleNavList=realSelectedList;
                    }
                }
            }
            if(currentUerAddNavList!=null){
                mAddNavList=currentUerAddNavList.getPortalNavBoList();
            }
            PortalSet portalSet = this.getPortalCacheManager().getPortalSetFromCache(portalId);
            String customSwitch = this.getPortalManager().getmTopOrMiddleCustomSwitch(portalSet);
            String item= "Mobile_"+ PortalConstants.MASTER_PORTAL;
            Long accountId = portalSet.getAccountId();
            String mobileMainPortalId= portalCacheManager.getPortalGlobalConfigFromCache(item, accountId, accountId);
            if(!("0".equals(customSwitch))){
                if(String.valueOf(portalId).equals(mobileMainPortalId)){
                    mTopOrMiddleNavCustomSwitch=true;
                }
            }

        }

        map.put("mBottomNav",bottomNavList);
        map.put("mTopOrMiddleNav",mTopOrMiddleNavList);
        map.put("mAddNav",mAddNavList);
        map.put("mTopOrMiddleNavCustomSwitch",mTopOrMiddleNavCustomSwitch);
        return map;
    }
    /**
     * 从两个list中取交集
     * @param cValues
     * @param spaces
     * @return
     */
    private Set<String> getIntersect(List<Map<String,String>> cValues, List<SpaceBO> spaces){
        Set<String> s1 = new LinkedHashSet<String>();
        Set<String> s2 = new LinkedHashSet<String>();
        for(Map<String,String> c:cValues){
            String spaceId = c.get("spaceId");
            s1.add(spaceId);
        }
        for(SpaceBO s:spaces){
            String spaceId = s.getSpaceId();
            s2.add(spaceId);
        }
        s1.retainAll(s2);
        if(s1.isEmpty()){
        	return s2;
        }
        return s1;
    }

	public FileManager getFileManager() {
		if (fileManager == null) {
			fileManager = (FileManager) AppContext.getBean("fileManager");
        }
        return fileManager;
	}
	
	/**
     * 门户空间——获取栏目依赖的第三方JS文件
     *
     * @param tplCodes tpl模板集合，多个之间用逗号隔开
     * @return
     */
	@Path("moduleJs")
    @GET
    @Consumes("*/*")
    @Produces("application/javascript")
    @ApiOperation(name = "获取栏目依赖的第三方JS文件", scenes = "M3：获取栏目依赖的第三方JS文件")
	public Response getModuleJs() throws Exception {
		String tplCodes = req.getParameter("tplCodes");//tpl模板集合，多个之间用逗号隔开
    	if(Strings.isBlank(tplCodes)){
    		return null;
    	}
    	String fd= "1";//来自哪个端：0表示PC端；1表示移动端
    	String[] tplCodeArr= tplCodes.split(",");
        Arrays.sort(tplCodeArr);//排下序，确保etag的顺序一致
        if("ALL".equals(tplCodes)){//所有moduleJS文件
        	tplCodeArr= null;
        }
        portalManager = (PortalManager) AppContext.getBean("portalManager");
        String jsContent= portalManager.getModuleJsContent(tplCodeArr,fd);
        if(Strings.isNotBlank(jsContent)){
        	resp.setContentType("text/javascript");
        	resp.setCharacterEncoding("UTF-8");
        	byte[] bout = jsContent.getBytes("UTF-8");
            resp.setIntHeader("Content-Length", bout.length);
        	return Response.ok(jsContent).build();
        }
		return null;
    }

    private void sortSpaceList(Map<String, Object> spaceList) {
        if (!"sc".equals(req.getHeader("m3-channel"))) {//智慧会议客户端
            return;
        }
        List<Map<String, Object>> data = (List<Map<String, Object>>) spaceList.get("data");
        if (CollectionUtils.isNotEmpty(data)) {
            List<Map<String, Object>> sortedData = data.stream().sorted((x, y) -> {
                if (ResourceUtil.getStringByLocaleAndParams("space.default.meeting.label", I18nUtil.parseLocale("zh-CN")).equals(x.get("spaceName"))) {
                    return -1;
                }
                return 0;
            }).collect(Collectors.toList());
            spaceList.put("data", sortedData);
        }
    }
}
